//
//  Sensors.m
//  PezMonkey
//
//  Created by Spence DiNicolantonio on 12/28/09.
//  Copyright 2009 Necrosoft. All rights reserved.
//

#import "Sensors.h"

#define kSensorsEmitterCollisionType 1
#define kSensorsCatcherCollisionType 2
#define kSensorsBallCollisionType 3

#define kSensorsEmitterVelocity 300
#define kSensorsMaxBalls 10


@implementation Sensors

@synthesize emitter;

- (NSString *)demoName {
	return @"Sensors";
}

- (void)start {
	// create space
	self.space = [PMSpace spaceWithGravity:PMVectMake(0, -1)];
	[space setSubSteps:3];
	[space setIterations:10];
	
	// initialize blocked flag
	blocked = NO;
	
	
	PMFloat radius = 15;
	
	// create emitter body
	PMBody *body = [PMBody staticBody];
	[body setPosition:PMVectMake(0, 150)];
	
	// create emitter shape
	self.emitter = [PMCircleShape circleShapeWithBody:body radius:radius];
	[emitter setSensor:YES];
	[emitter setCollisionType:kSensorsEmitterCollisionType];
	[emitter setLayers:PMLayerMaskNotGrabbable];
	[space addStaticShape:emitter];
	
	// create catcher
	PMShape *shape = [PMSegmentShape segmentShapeWithBody:[PMBody staticBody] 
													start:PMVectMake(-2000, -200)
													  end:PMVectMake(2000, -200)
													width:radius*2];
	[shape setSensor:YES];
	[shape setLayers:PMLayerMaskNotGrabbable];
	[shape setCollisionType:kSensorsCatcherCollisionType];
	[space addStaticShape:shape];
	
	// register collision callbacks
	[space registerCollisionCallbackTarget:self 
								  selector:@selector(emitterCollision:) 
								  forTypeA:kSensorsBallCollisionType 
									 typeB:kSensorsEmitterCollisionType];
	[space registerCollisionCallbackTarget:self 
								  selector:@selector(catcherCollision:) 
								  forTypeA:kSensorsBallCollisionType 
									 typeB:kSensorsCatcherCollisionType];
}

- (void)update:(NSTimeInterval)deltaT {
	// add new ball?
	if (!blocked)// && [[space activeShapes] count] < kSensorsMaxBalls)
		[self emitBall];
}

/**
 * Creates a ball at the emitter with random velocity.
 */
- (void)emitBall {
	if (!emitter)
		return;
	
	// define ball attributes
	PMFloat mass = 1.0;
	PMFloat radius = ((PMCircleShape *) emitter).radius;
	PMFloat moment = PMMomentForCircle(mass, 0, radius, PMVectZero);
	PMVect position = emitter.body.position;
	PMVect velocity = PMVectMult(PMVectMake(2*PMFloatRandom()-1, 
											2*PMFloatRandom()-1), 
								 kSensorsEmitterVelocity);
	velocity.y = fabs(velocity.y);
	
	// create ball body
	PMBody *body = [PMBody bodyWithMass:mass moment:moment];
	[body setPosition:position];
	[body setVelocity:velocity];
	[space addBody:body];
	
	// create ball shape
	PMShape *shape = [PMCircleShape circleShapeWithBody:body radius:radius];
	[shape setCollisionType:kSensorsBallCollisionType];
	[space addShape:shape];
}


#pragma mark -
#pragma mark Dealloc

- (void)catcherCollision:(PMCollision *)collision {
	if (collision.state == PMCollisionStateBegan) {
	
		// get ball shape
		PMShape *ball = collision.shapeA; 
		if (collision.shapeB.collisionType == kSensorsBallCollisionType)
			ball = collision.shapeB;
		
		// remove ball
		[space postStepRemoveShapeAndBody:ball];
	}
}

- (void)emitterCollision:(PMCollision *)collision {
	if (collision.state == PMCollisionStateBegan)
		// block emitter until created ball leaves perimeter
		blocked = YES;
	
	if (collision.state == PMCollisionStateEnded)
		// unblock emitter now that the perimeter is clear
		blocked = NO;
}


#pragma mark -
#pragma mark Dealloc

- (void)dealloc {
	[emitter release];
	[super dealloc];
}

@end
